/**
 * User类, 用于操作leancloud的用户相关操作.
 */
class $User {
  constructor(AV, defaultACL, request, that) {
    this.AV = AV
    this.$http = new AV.User()
    this.defaultACL = defaultACL
    this.request = request
    this.that = that
    this.avObject = null
  }

  current() {
    const dispatchRequest = this.AV.User.current()
    this.avObject = dispatchRequest
    return dispatchRequest
  }

  getCurrentRoles() {
    const { $http, request, avObject, that } = this
    const dispatchRequest = () =>
      avObject ? avObject.fetch() : this.current().getRoles()
    return request.call(that, dispatchRequest)
  }

  async getInfo() {
    const { $http, request, avObject, that } = this
    const userAV = avObject || this.current()
    const userData = userAV.toJSON()
    const roles = await userAV.getRoles()
    userData.roles = roles.map((item) => item.toJSON().name)
    return userData
  }

  setUsername(username) {
    const { $http, avObject } = this
    this.$http.setUsername(username)
    return this
  }

  setPassword(password) {
    const { $http, avObject } = this
    $http.setPassword(password)
    return this
  }

  setEmail(email) {
    const { $http } = this
    $http.setEmail(email)
    return this
  }

  setMobilePhoneNumber(mobile) {
    const { $http } = this
    $http.setMobilePhoneNumber(email)
    return this
  }

  // 注册user
  signUp() {
    const { $http, request, that } = this
    const dispatchRequest = () => $http.signUp()
    return request.call(that, dispatchRequest)
  }

  // 登陆
  logIn({ username, password, email, mobile }) {
    const { AV, request, that } = this
    let dispatchRequest = null
    if (!password) return
    if (username) dispatchRequest = () => AV.User.logIn(username, password)
    if (email) dispatchRequest = () => AV.User.loginWithEmail(email, password)
    if (mobile)
      dispatchRequest = () => AV.User.logInWithMobilePhone(mobile, password)
    return request.call(that, dispatchRequest)
  }

  // 登出
  logOut() {
    const { AV, request, that } = this
    const dispatchRequest = () => AV.User.logOut()
    return request.call(that, dispatchRequest)
  }

  // 验证邮箱
  requestEmailVerify(email) {
    const { AV, request, that } = this
    const dispatchRequest = () => AV.User.requestEmailVerify(email)
    return request.call(that, dispatchRequest)
  }

  // 验证手机号
  requestMobilePhoneVerify(mobile) {
    const { AV, request, that } = this
    const dispatchRequest = () => AV.User.requestMobilePhoneVerify(mobile)
    return request.call(that, dispatchRequest)
  }

  // 使用邮箱重置密码
  requestPasswordReset(email) {
    const { AV, request, that } = this
    const dispatchRequest = () => AV.User.requestPasswordReset(email)
    return request.call(that, dispatchRequest)
  }

  // 同步云端数据
  fetch() {
    const { $http, avObject, request, that } = this
    const dispatchRequest = () => (avObject ? avObject.fetch() : $http.fetch())
    return request.call(that, dispatchRequest)
  }

  loginWithEmail({ email, password }) {
    const { AV, request, that } = this
    const dispatchRequest = () => AV.User.loginWithEmail(email, password)
    return request.call(that, dispatchRequest)
  }

  logInWithMobilePhone({ mobile, password }) {
    const { AV, request, that } = this
    const dispatchRequest = () => AV.User.logInWithMobilePhone(mobile, password)
    return request.call(that, dispatchRequest)
  }

  //* 使用token登陆账户
  become(token) {
    const { AV, request, that } = this
    const dispatchRequest = () => AV.User.become(token)
    return request.call(that, dispatchRequest)
  }

  requestPasswordResetBySmsCode(mobile) {
    const { AV, request, that } = this
    const dispatchRequest = () => AV.User.requestPasswordResetBySmsCode(mobile)
    return request.call(that, dispatchRequest)
  }

  // 个人定制API
  /**
   * 注册用户
   * @param {Object} parmas - 注册参数
   * @param {String} parmas.username - 登录名
   * @param {String} parmas.password - 登录密码
   * @param {String} parmas.email - 邮箱
   * @param {String} parmas.mobile - 手机号码
   * @param {String} parmas.acl  注册用户的默认acl 参数详情对照acl中的createACL函数
   * @return {Object} LeanCloud用户对象
   */
  register({ username, password, email, mobile, acl }) {
    const { request, $http, that, defaultACL } = this
    if (defaultACL) $http.setACL(defaultACL)
    if (username) this.setUsername(username)
    if (password) this.setPassword(password)
    if (email) this.setEmail(email)
    if (mobile) this.setMobilePhoneNumber(mobile)
    if (acl) $http.setACL(acl)
    const dispatchRequest = () => this.signUp()
    return request.call(that, dispatchRequest)
  }

  /**
   * 为用户添加角色
   * @param {Object} parmas - 参数
   * @param {String} parmas.userId - 需要添加的用户ObjectId
   * @param {String} parmas.roleId - 需要添加至的角色ObjectId
   * @return {Object} 添加状态
   */
  addMember2Role({ userId, roleId }) {
    const { AV, $http, request, that } = this
    const userAV = that.Object().createWithoutData(AV.User, userId).avObject
    const roleAV = that.Object().createWithoutData(AV.Role, roleId).avObject
    roleAV.getUsers().add(userAV)
    const dispatchRequest = () => roleAV.save()
    return request.call(that, dispatchRequest)
  }

  /**
   * 查询项目中的注册用户列表 (使用需手动开启_User权限中的find权限)
   * @param {Object} parmas - 参数
   * @param {Array} parmas.filter 筛选项 参数请参照Query类中的getData函数
   * @return {Array} leancloud 用户列表
   */
  searchUser({ filter }) {
    const { AV, $http, request, that } = this
    const http = that.Query(AV.User)
    const lcFilter = []
    if (filter) {
      filter.forEach((item) => {
        const rule = item
        const lcFilterRow = {}
        const key = Object.keys(rule)[0]
        switch (key) {
          default:
            lcFilterRow[key] = rule[key]
            lcFilter.push(lcFilterRow)
        }
      })
    }
    if (lcFilter.length > 0) {
      lcFilter.forEach((row) => {
        const key = Object.keys(row)[0]
        const rule = {}
        rule[key] = row[key]
        http.equalTo(rule)
      })
    }
    return http.first()
  }
}
export default $User
